package com.gitee.yangtianle.redisson.seckill.interceptor;

import com.gitee.yangtianle.redisson.seckill.annotation.SingleCurrentLimit;
import com.google.common.util.concurrent.RateLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author tianle.ytl
 * @date 2018/9/19
 */
public class SingleCurrentLimitInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(SingleCurrentLimitInterceptor.class);

    private RateLimiter rateLimiter;

    public SingleCurrentLimitInterceptor(RateLimiter rateLimiter) {
        this.rateLimiter = rateLimiter;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Class<?> clz = method.getDeclaringClass();
        SingleCurrentLimit singleCurrentLimit = method.getAnnotation(SingleCurrentLimit.class);
        rateLimiter.setRate(singleCurrentLimit.permitsPerSecond());

        boolean temp = rateLimiter.tryAcquire();
        logger.info("{}.{} request {}.", clz.getName(), method.getName(), temp ? "success" : "failed");
        if (temp) {
            return true;
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }

    public RateLimiter getRateLimiter() {
        return rateLimiter;
    }

    public void setRateLimiter(RateLimiter rateLimiter) {
        this.rateLimiter = rateLimiter;
    }
}
